iT邦幫忙

2024 iThome 鐵人賽

DAY 4
0

目標

  1. 認識 Security Context
  2. 為 Quarkus 應用程式配置 Security Context

在 Linux 系統上,實務上可能要調整 netkernel 等參數,而要修改這些參數需要提權。在 Kubernetes 上則需要使用 Security Context,其目的是限制容器不要非法操作影響節點。這些設定允許維運貨管理者控制容器運行時環境的安全面。這在多租戶叢集環境中至關重要,因為不同使用者的工作負載之間的隔離可以減少影響或攻擊面。在 Pod 資源上有兩種級別

  1. spec.securityContext
  2. spec.containers[].securityContext

接下來將探討 Security Context 細節部分。上一章節將 Quarkus 部署至 Kubernetes 環境中,且服務可以順利運行。然而以開發者角度來看其實可能不會注重安全性上的配置,以 Quarkus 的 Kubernetes 依賴來說,它並沒有為服務產生一個預設安全性即 Security Context 配置,想當然這就比較不會被注意。

部署到 Kubernetes 上的 Quarkus 服務權限到底是如何 ? 首先,透過 exec 方式進到 Pod 中的容器。

$ kubectl exec ithome2024lab-74959699f7-zq5gx -it /bin/bash

下面的操作顯示了當前 Pod 是否以 root 身分執行且是否具有一些 CAP 相關的操作能力。看到之後發現其權限特別的大,這會有一定的風險,即攻擊面範圍廣。

bash-4.4# id
uid=0(root) gid=0(root) groups=0(root)
bash-4.4# capsh --print
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Ambient set =
Current IAB: !cap_dac_read_search,!cap_linux_immutable,!cap_net_broadcast,!cap_net_admin,!cap_ipc_lock,!cap_ipc_owner,!cap_sys_module,!cap_sys_rawio,!cap_sys_ptrace,!cap_sys_pacct,!cap_sys_admin,!cap_sys_boot,!cap_sys_nice,!cap_sys_resource,!cap_sys_time,!cap_sys_tty_config,!cap_lease,!cap_audit_control,!cap_mac_override,!cap_mac_admin,!cap_syslog,!cap_wake_alarm,!cap_block_suspend,!cap_audit_read,!cap_perfmon,!cap_bpf,!cap_checkpoint_restore
Securebits: 00/0x0/1'b0 (no-new-privs=0)
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
 secure-no-ambient-raise: no (unlocked)
uid=0(root) euid=0(root)
gid=0(root)
groups=0(root)
Guessed mode: UNCERTAIN (0)
bash-4.4#

到這繼續先探討 Security Context,從上面的介紹來看,其有 Pod 層級和容器層級的配置。下面列出個別對應的配置內容,如果是有描述即應用上有特別配置過或是特別看過其功能。更詳細的內容可參考官方 security-context 介紹。

Pod Security Context

  1. fsGroup 指定 Pod 中所有磁碟區的群組 ID
  2. fsGroupChangePolicy
  3. supplementalGroups
  4. sysctls 用於調整容器的網路、記憶體或檔案系統等方面行為。像是 net.ipv4.tcp_tw_recycle

Container Security Context

  1. allowPrivilegeEscalation 容器中的 process 無法提升其權限
  2. capabilities 新增或刪除容器的操作權限
  3. privileged 容器是否取得所有權限,包括存取主機 device 或是 network 等
  4. procMount 對 /proc 檔案系統存取限制
  5. readOnlyRootFilesystem 容器的 root 檔案系統是摟設定為唯讀

兩者都可

  1. runAsGroup 指定 Pod 中所有容器執行時的群組 ID
  2. runAsNonRoot 容器是否以 root 使用者身分執行
  3. runAsUser 指定 Pod 中所有容器執行時使用者 ID
  4. seLinuxOptions
  5. seccompProfile
  6. windowsOptions

隨著 Kubernetes 不同版本的發布,其內容有可能是增加或是刪除。

Quarkus 在 Kubernetes 的 Security Context

將 Quarkus 的 Deployment 資源新增以下 SecurityContext 欄位配置。

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/quarkus-version: 3.13.3
    app.quarkus.io/commit-id: 1935a62ca5ef3e7242ba80b9ee3f27ed08d875b4
    app.quarkus.io/build-timestamp: 2024-08-24 - 10:11:15 +0000
  labels:
    app.kubernetes.io/name: ithome2024lab
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: ithome2024lab-day04
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ithome2024lab-day04
      app.kubernetes.io/version: 1.0.0-SNAPSHOT
  template:
    metadata:
      annotations:
        app.quarkus.io/quarkus-version: 3.13.3
        app.quarkus.io/commit-id: 1935a62ca5ef3e7242ba80b9ee3f27ed08d875b4
        app.quarkus.io/build-timestamp: 2024-08-24 - 10:11:15 +0000
      labels:
        app.kubernetes.io/managed-by: quarkus
        app.kubernetes.io/name: ithome2024lab-day04
        app.kubernetes.io/version: 1.0.0-SNAPSHOT
      namespace: default
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 2000
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: registry.hub.docker.com/cch0124/ithome2024lab:1.0.0-SNAPSHOT
          imagePullPolicy: Always
          securityContext:
            privileged: false
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              add:
                - CAP_SYS_ADMIN
              drop:
                - ALL
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/live
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          name: ithome2024lab
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/ready
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          startupProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/started
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10

使用 Quarkus 提供的依賴來設定,可以如下。但有些欄位是無提供設定。

quarkus:
  kubernetes:
    namespace: default
    security-context:
      run-as-user: 1000
      run-as-group: 1000
      run-as-non-root: true
      fs-group: 2000

透過 kubectl apply 建置後,查看 Log 其實會有錯。即對於 /tmp/vertx-cache 讀寫權限不夠。

$ kubectl apply -f kubernetes/kubernetes-local.yml
$ kubectl logs -f ithome2024lab-day04-bd6587c6f-nw2nl 
Aug 25, 2024 6:00:28 AM io.quarkus.vertx.core.runtime.VertxCoreRecorder
WARN: Unable to create Vert.x cache directory : /tmp/vertx-cache
Aug 25, 2024 6:00:28 AM io.quarkus.vertx.core.runtime.VertxCoreRecorder
WARN: Unable to make the Vert.x cache directory (/tmp/vertx-cache) world readable and writable
Aug 25, 2024 6:00:28 AM io.quarkus.runtime.ApplicationLifecycleManager run

如果將 readOnlyRootFilesystem 改成 false 即可正常運行,如下驗證。

$ kubectl port-forward deployment/ithome2024lab-day04 8080
$ curl http://localhost:8080/hello
Hello RESTEasy hello

readOnlyRootFilesystem 表示容器的 root 檔案系統是只讀的,即容器內的進程一般不能直接修改檔案系統。這邊嘗試使用 EmptyDir Volume 方式來解決上面問題,而非設定 readOnlyRootFilesystem。如下

apiVersion: apps/v1
kind: Deployment
metadata:
  ....
  name: ithome2024lab-day04
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ithome2024lab-day04
      app.kubernetes.io/version: 1.0.0-SNAPSHOT
  template:
    ....
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 2000
      volumes: # 這邊
        - name: vertx-cache
          emptyDir: {}
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: registry.hub.docker.com/cch0124/ithome2024lab:1.0.0-SNAPSHOT
          volumeMounts: # 這邊
          - name: vertx-cache
            mountPath: /tmp/vertx-cache
          imagePullPolicy: Always
          securityContext:
            privileged: false
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
...

此時我們 exec 至容器內部,可以發現使用這不在是 root,而且也無法隨意建立檔案。這樣的設定讓攻擊範圍面縮小很多,實務上非常建議配置。

$ kubectl exec -it ithome2024lab-day04-b4547f754-hjqrv -it /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-4.4$ id
uid=1000 gid=1000 groups=1000,2000
bash-4.4$ pwd
/work
bash-4.4$ capsh --print
Current: =
Bounding set =
Ambient set =
Current IAB: !cap_chown,!cap_dac_override,!cap_dac_read_search,!cap_fowner,!cap_fsetid,!cap_kill,!cap_setgid,!cap_setuid,!cap_setpcap,!cap_linux_immutable,!cap_net_bind_service,!cap_net_broadcast,!cap_net_admin,!cap_net_raw,!cap_ipc_lock,!cap_ipc_owner,!cap_sys_module,!cap_sys_rawio,!cap_sys_chroot,!cap_sys_ptrace,!cap_sys_pacct,!cap_sys_admin,!cap_sys_boot,!cap_sys_nice,!cap_sys_resource,!cap_sys_time,!cap_sys_tty_config,!cap_mknod,!cap_lease,!cap_audit_write,!cap_audit_control,!cap_setfcap,!cap_mac_override,!cap_mac_admin,!cap_syslog,!cap_wake_alarm,!cap_block_suspend,!cap_audit_read,!cap_perfmon,!cap_bpf,!cap_checkpoint_restore
Securebits: 00/0x0/1'b0 (no-new-privs=1)
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
 secure-no-ambient-raise: no (unlocked)
uid=1000(???) euid=1000(???)
gid=1000(???)
groups=1000(???),2000(???)
Guessed mode: UNCERTAIN (0)
bash-4.4$ stat -c "%u %g" /proc/1/
1000 1000

看看這效果挺不錯的。安全人人有責。

  1. runAsUser 與 runAsGroup

預設情況下,容器以 root 身分執行,該身分基本上有完全管理權。這是一個安全風險,畢竟任何想利用容器的進程都有機會獲取本機系統的 root 存取權。因此可以透過 securityContext 來配置特定的使用者與群組,範例指定 1000:1000。

  1. capabilities

是一組可授予 Linux 系統中進程的權限。如果想為容器提供 ping 操作功能可以新增 CAP_NET_RAW 權限,又或者想防止更改檔案的擁有者,可以刪除 CAP_CHOWN 權限。本範例是把全部權限拔掉,畢竟該服務單純提供 API 並沒有要求底層資源。

  1. fsGroup

指定了一個群組 ID,應該與容器掛載的任何卷(volume)相關聯。這允許該組讀取和寫入卷,即使卷的檔案系統本身不支持 POSIX 所有權或權限。白話一點是 fsGroup 就像是一個通行證,告訴容器它可以以某個特定身份即組 ID來訪問卷。有了這個身份,容器就能像檔案系統的"主人"一樣對卷進行操作。以本範例來看 ID 設定 2000,同時有掛載一個卷即 vertx-cache,在這 Pod 中運行的容器就可使用群組 2000 來存去這個卷,從下面結果可以知道,並對卷中的檔案進行讀寫操作。

bash-4.4$ ls -l /tmp/
total 4
drwxrwsrwx 2 root 2000 4096 Aug 25 09:44 vertx-cache
bash-4.4$ id 
uid=1000 gid=1000 groups=1000,2000
  1. readOnlyRootFilesystem

root 檔案系統是否應該是唯讀。如果是,則容器將無法寫入其 root 檔案系統。建至 Image 時就定義了容器的 root 檔案系統,像是 /etc/var 等。基本上可防止檔案被修改。

bash-4.4$ mkdir test
mkdir: cannot create directory 'test': Read-only file system
  1. AllowPrivilegeEscalation

即進程是否可以獲得比父進程更多的權限。如果設定是 false,則容器中的進程將無法獲得額外的權限,從而有效地防止權限提升攻擊。實驗範例設定為 false

  1. privileged

用來控制容器是否以特權模式運行。當為 true 時,容器內的進程將獲得與本機相同的權限,即 root 權限,使容器內的進程可以執行任何操作。

到這邊,基本上熟悉了部分的 SecurityContext 設置。但是,對於內部團隊要如何規範這些內容是值得思考,可能是使用 OPA 或是 Kyverno 等進行全面控管。

額外與參考資源


上一篇
地端部署 Quarkus 專案至 Kubernetes 環境
下一篇
Quarkus 你健康了嗎 ?
系列文
當 Quarkus 想要騎乘駱駝並用8腳章魚掌控舵手 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言